package com.xbongbong.paas.enums;

import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import lombok.Getter;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author zcp
 * @version v1.0
 * @since v1.0
 */
@Getter
public enum PaySheetTypeEnum {

    /**
     * code："1"
     * 已核销（已核销的alias没有用XbbRefTypeEnum.PAY_SHEET的alias）
     * 入口：付款单列表、采购合同详情、付款计划列表、付款计划详情、供应商详情
     * 付款，直接核销。此类付款单是原线上已有流程业务，新建付款单时必须关联供应商、采购合同(可关联付款计划)，故而将称之为“直接核销”付款单
     */
    WRITE_OFF_PAY(SheetTypeEnum.WRITE_OFF_PAY.getCode(), SheetTypeEnum.WRITE_OFF_PAY.getI18nName(), SheetTypeEnum.WRITE_OFF_PAY.getAlias(), XbbRefTypeEnum.PAY_SHEET.getCode(), SheetTypeEnum.WRITE_OFF_PAY),

    /**
     * code："2"
     * 预付款核销
     * 入口：预付款列表、预付款明细、采购合同详情、付款计划详情
     */
    WRITE_OFF_PREPAY(SheetTypeEnum.WRITE_OFF_PREPAY.getCode(), SheetTypeEnum.WRITE_OFF_PREPAY.getI18nName(), SheetTypeEnum.WRITE_OFF_PREPAY.getAlias(), XbbRefTypeEnum.WRITE_OFF_PREPAY.getCode(), SheetTypeEnum.WRITE_OFF_PREPAY),

    /**
     * code："3"
     * 预付款
     * 入口：预付款列表
     */
    PREPAY(SheetTypeEnum.PREPAY.getCode(), SheetTypeEnum.PREPAY.getI18nName(), SheetTypeEnum.PREPAY.getAlias(), XbbRefTypeEnum.PREPAY.getCode(), SheetTypeEnum.PREPAY),

    /**
     * code："4","5","6"
     * 入口：原付款单详情、预付款明细、预付款核销单详情、新建退款退款时-红冲
     */
    //"4"，红冲已核销
    RED_WRITE_OFF_PAY(SheetTypeEnum.RED_WRITE_OFF_PAY.getCode(), SheetTypeEnum.RED_WRITE_OFF_PAY.getI18nName(), SheetTypeEnum.RED_WRITE_OFF_PAY.getAlias(), XbbRefTypeEnum.RED_WRITE_OFF_PAY.getCode(), SheetTypeEnum.RED_WRITE_OFF_PAY),
    //"5"，红冲预收款核销
    RED_WRITE_OFF_PREPAY(SheetTypeEnum.RED_WRITE_OFF_PREPAY.getCode(), SheetTypeEnum.RED_WRITE_OFF_PREPAY.getI18nName(), SheetTypeEnum.RED_WRITE_OFF_PREPAY.getAlias(), XbbRefTypeEnum.RED_WRITE_OFF_PREPAY.getCode(), SheetTypeEnum.RED_WRITE_OFF_PREPAY),
    //"6"，红冲预收款余额
    RED_PREPAY(SheetTypeEnum.RED_PREPAY.getCode(), SheetTypeEnum.RED_PREPAY.getI18nName(), SheetTypeEnum.RED_PREPAY.getAlias(), XbbRefTypeEnum.RED_PREPAY.getCode(), SheetTypeEnum.RED_PREPAY),

    /**
     * code："7"
     * 坏账
     * 入口：合同详情、付款计划详情
     */
    BAD_PAY(SheetTypeEnum.BAD_PAY.getCode(), SheetTypeEnum.BAD_PAY.getI18nName(), SheetTypeEnum.BAD_PAY.getAlias(), XbbRefTypeEnum.BAD_PAY.getCode(), SheetTypeEnum.BAD_PAY),

    /**
     * 未知
     */
    UNKNOWN(SheetTypeEnum.UNKNOWN.getCode(), SheetTypeEnum.UNKNOWN.getI18nName() , XbbRefTypeEnum.UNKNOWN.getAlias(), XbbRefTypeEnum.UNKNOWN.getCode(), SheetTypeEnum.UNKNOWN),
    ;

    /**
     * 类型code值
     */
    private String code;

    /**
     * 类型名称
     */
    private String name;

    /**
     * 类型attr
     */
    private String alias;

    /**
     * 业务code
     */
    private Integer businessType;

    /**
     * 回款单、付款单总枚举
     */
    private SheetTypeEnum sheetTypeEnum;

    PaySheetTypeEnum(String code, String name, String alias, Integer businessType, SheetTypeEnum sheetTypeEnum){
        this.code = code;
        this.name = name;
        this.alias = alias;
        this.businessType = businessType;
        this.sheetTypeEnum = sheetTypeEnum;
    }

    /**
     * 根据类型code得到付款单枚举
     * @param code 付款类型code
     * @return com.xbongbong.paas.enums.PaySheetTypeEnum
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public static PaySheetTypeEnum getByCode(String code) {
        for (PaySheetTypeEnum cacheCode : values()) {
            if (Objects.equals(code, cacheCode.getCode())) {
                return cacheCode;
            }
        }
        return UNKNOWN;
    }

    /**
     * 通过枚举 businessType 获得枚举
     * @param businessType
     * @return com.xbongbong.paas.enums.PaymentSheetTypeEnum
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public static PaySheetTypeEnum getByBusinessType(Integer businessType) {
        if (Objects.equals(businessType, XbbRefTypeEnum.PREPAY_BALANCE.getCode())) {
            //如果是预付款列表类型，则也返回预付款枚举：预付款余额是一个单独的列表，有自己的XbbRefTypeEnum，但是其本质还是预付款类型
            return PREPAY;
        }
        for (PaySheetTypeEnum cacheCode : values()) {
            if (Objects.equals(businessType, cacheCode.businessType)) {
                return cacheCode;
            }
        }
        return UNKNOWN;
    }

    /**
     * 根据普通回款单类型code，得到其本身的businessType
     * 回款单编辑、删除、打印按钮，要基于回款单类型得到businessType：因为回款单详情打开前端拿到的都是702，而要根据回款单data内的paymentSheetType确定具体是哪种类型回款单
     * @param code
     * @return java.lang.Integer
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public static Integer getBusinessTypeByCode(String code) {
        PaySheetTypeEnum cache = getByCode(code);
        return cache.businessType;
    }

    /**
     * 判断是否是创建/编辑付款单
     * @param sheetTypeEnum 回款单/付款单 类型总枚举
     * @return boolean true 创建/编辑付款单，false 不是任何一种付款单业务
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public static boolean validateSheet(SheetTypeEnum sheetTypeEnum) {
        return sheetTypeEnum != null && Objects.equals(sheetTypeEnum.getXbbRefTypeEnum(), XbbRefTypeEnum.PAY_SHEET);
    }

    /**
     * 红冲类型
     *
     * @return java.util.List<java.lang.String>
     * @author 徐俊杰
     * @date 2019/12/5 11:11
     * @since v1.0
     */
    public static List<String> getRedCodeList() {
        return Arrays.asList(RED_WRITE_OFF_PAY.code, RED_WRITE_OFF_PREPAY.code, RED_PREPAY.code);
    }
    /**
     * 根据付款单类型判断是否为红冲类型
     * @param type 付款单类型
     * @return 是否为红冲 true为红冲
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public static boolean isRed(String type){
        return getRedCodeList().contains(type);
    }

    /**
     * 根据回款单类型判断是否为核销类型（不包含预收款回款单类型）
     * @param type 回款单类型
     * @return 是否为核销 true为核销
     * @author zhouwq
     * @date 2019/10/31 15:53
     */
    public static boolean isWriteOff(String type){
        return Objects.equals(type, WRITE_OFF_PAY.code) || Objects.equals(type, WRITE_OFF_PREPAY.code);
    }

    /**
     * 根据付款单类型判断是否为坏账类型
     * @param type 付款单类型
     * @return boolean
     * @author zcp
     * @since v1.0
     */
    public static boolean isBad(String type) {
        return Objects.equals(BAD_PAY.code, type);
    }

    /**
     * 根据businessType判断是否为红冲类型
     * @param businessType 业务code
     * @return 是否为红冲
     * @author zhouwq
     * @date 2019/12/12 11:35
     */
    public static boolean isRedByBusinessType(Integer businessType) {
        return Objects.equals(businessType, RED_PREPAY.businessType) || Objects.equals(businessType, RED_WRITE_OFF_PREPAY.businessType) || Objects.equals(businessType, RED_WRITE_OFF_PAY.businessType);
    }

    /**
     * 根据businessType判断是否为已核销/预收款类型
     * @param businessType 业务code
     * @return 是否为已核销/预收款类型
     * @author zhouwq
     * @date 2019/12/12 11:35
     */
    public static boolean isWriteOffByBusinessType(Integer businessType) {
        return Objects.equals(businessType, WRITE_OFF_PAY.businessType) || Objects.equals(businessType, WRITE_OFF_PREPAY.businessType) || Objects.equals(businessType, PREPAY.businessType);
    }

    /**
     * 得到所有预付款相关类型code集合
     * （当预付款菜单未开启时，所有预付款相关的付款单类型都应该隐藏）
     * @return java.util.List<java.lang.String>
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public static List<String> getPrepayCodeList() {
        return Arrays.asList(WRITE_OFF_PREPAY.code, PREPAY.code, RED_WRITE_OFF_PREPAY.code, RED_PREPAY.code);
    }

    /**
     * 根据普通付款单类型code，得到对应的红冲类型的XbbRefTypeEnum的code
     * @param code 付款单类型type
     * @return java.lang.String
     * @author zcp
     * @date 19/12/2 002 19:39
     * @update 19/12/2 002 19:39
     * @since v1.0
     * @version v1.0
     */
    public static Integer getRedBusinessTypeByCode(String code) {
        if (Objects.equals(code, WRITE_OFF_PAY.code)) {
            //code为已核销，则返回【红冲】已核销的businessType
            return RED_WRITE_OFF_PAY.businessType;
        } else if (Objects.equals(code, WRITE_OFF_PREPAY.code)) {
            //code为预付款核销，则返回【红冲】预付款核销的businessType
            return RED_WRITE_OFF_PREPAY.businessType;
        } else if (Objects.equals(code, PREPAY.code)) {
            //code为预付款，则返回【红冲】预付款的businessType
            return RED_PREPAY.businessType;
        }
        return UNKNOWN.businessType;
    }

    /**
     * 中文名称获取枚举
     *
     * @param name 名称
     * @return com.xbongbong.paas.enums.PaySheetTypeEnum
     * @author 徐俊杰
     * @date 2020/3/3 14:20
     * @since v1.0
     */
    public static PaySheetTypeEnum getByName(String name) {
        for (PaySheetTypeEnum cache : values()) {
            if (Objects.equals(name, cache.getName())) {
                return cache;
            }
        }
        return UNKNOWN;
    }

    /**
     * 获取非坏账的codeList
     *
     * @return java.util.List<java.lang.String>
     * @author 徐俊杰
     * @date 2020/3/7 14:26
     * @since v1.0
     */
    public static List<String> getNotBadCodeList() {
        List<String> notBadCodeList = new ArrayList<>();
        for (PaySheetTypeEnum cache : values()) {
            if (Objects.equals(PaySheetTypeEnum.BAD_PAY, cache) || Objects.equals(PaySheetTypeEnum.UNKNOWN, cache)) {
                continue;
            }
            notBadCodeList.add(cache.code);
        }
        return notBadCodeList;
    }

    /**
     * 付款核销只统计4种：已核销、预付款核销、红冲已核销、红冲预付款核销
     * @return java.util.List<java.lang.String>
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public static List<String> getWriteOffCodeList(){
        return Arrays.asList(WRITE_OFF_PAY.code, WRITE_OFF_PREPAY.code, RED_WRITE_OFF_PAY.code, RED_WRITE_OFF_PREPAY.code);
    }

    /**
     * 坏账类型
     *
     * @return java.util.List<java.lang.String>
     * @author 徐俊杰
     * @date 2019/12/5 11:12
     * @since v1.0
     */
    public static List<String> getBadCodeList() {
        return Collections.singletonList(BAD_PAY.code);
    }

    /**
     * 获取资金账户收支情况的codeList
     *
     * @return java.util.List<java.lang.String>
     * @author 徐俊杰
     * @date 2020/3/18 15:29
     * @since v1.0
     */
    public static List<String> getCodeList4FundAccount() {
        List<String> codeList = new ArrayList<>();
        for (PaySheetTypeEnum cache : values()) {
            if (Objects.equals(PaySheetTypeEnum.WRITE_OFF_PREPAY, cache) || Objects.equals(PaySheetTypeEnum.BAD_PAY, cache) || Objects.equals(PaySheetTypeEnum.UNKNOWN, cache)) {
                continue;
            }
            codeList.add(cache.code);
        }
        return codeList;
    }

    /**
     * 获取无 预付款、红冲预付款余额的类型
     * @return java.util.List<java.lang.String>
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public static List<String> getCodeList4NoPre(){
        List<String> codeList = new ArrayList<>();
        for (PaySheetTypeEnum cache : values()) {
            if (Objects.equals(PaySheetTypeEnum.PREPAY, cache) || Objects.equals(PaySheetTypeEnum.RED_PREPAY, cache) || Objects.equals(PaySheetTypeEnum.UNKNOWN, cache)) {
                continue;
            }
            codeList.add(cache.code);
        }
        return codeList;
    }

    public String getName() {
        return I18nMessageUtil.getMessage(name);
    }
    public String getI18nName() {
        return name;
    }

    /**
     *
     * @Description: 获取所有付款单类型的业务code
     * @param
     * @return: java.util.List<java.lang.Integer>
     * @Author: shen.yang
     * @Date: 2022/3/29  15:56
     */
    public static List<Integer> getAllBusinessType(){
        return Arrays.stream(PaySheetTypeEnum.values()).filter(v -> !Objects.equals(v.getCode(),UNKNOWN.getCode())).map(PaySheetTypeEnum::getBusinessType).collect(Collectors.toList());
    }
    /**
     *
     * @Description: 获取除去预付款和红冲预付款余额之外的所有付款单code（用于团队继承）
     * @param
     * @return: java.util.List<java.lang.Integer>
     * @Author: shen.yang
     * @Date: 2022/3/29  16:02
     */
    public static List<Integer> getBusinessTypeExcludePre(){
        return getAllBusinessType().stream().filter(v -> !Arrays.asList(PREPAY.getBusinessType(),RED_PREPAY.getBusinessType()).contains(v)).collect(Collectors.toList());
    }
}
